package com.kaibes.web.prefix;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class PrefixContext {

    @Autowired
    private ResourceRegistrys registrys;
    
    @Value("${spring.thymeleaf.prefix:templates/}")
    private String prefix;
    
    private List<PrefixTarget> prefixTargetList = new ArrayList<>();
    private PrefixTarget defaultPrefixTarget = new PrefixTarget();
    private static final String base = "/**";
    
    public void clear() {
        prefixTargetList.clear();
    }
    
    public PrefixContext addPrefixTarget(PrefixTarget prefixTarget) {
        PrefixTarget oldTarget = findPrefixTarget(prefixTarget.getPrefix());
        if (prefixTarget.getPrefix().isEmpty()) {
            if (oldTarget != null) {
                unregistry(base, oldTarget);
            }
            defaultPrefixTarget = prefixTarget;
            registry(base, prefixTarget);
        } else {
            PrefixTarget temp = findPrefixTarget(prefixTarget.getPrefix());
            if (temp != null) {
                prefixTargetList.remove(temp);
            }
            prefixTargetList.add(prefixTarget);
            String path = new StringBuilder("/").append(prefixTarget.getPrefix()).append("/**").toString();
            if (oldTarget != null) {
                unregistry(path, oldTarget);
            }
            registry(path, prefixTarget);
        }
        return this;
    }
    
    public PrefixTarget getDefaultPrefixTarget() {
        return defaultPrefixTarget;
    }
    
    public PrefixTarget findPrefixTarget(String prefix) {
        if (prefix.trim().isEmpty()) {
            return defaultPrefixTarget;
        }
        for (int i = 0; i < prefixTargetList.size(); i++) {
            PrefixTarget temp = prefixTargetList.get(i);
            if (temp.getPrefix().equals(prefix)) {
                return temp;
            }
        }
        return null;
    }

    public PrefixTarget findPrefixTargetByUri(String uri) {
        byte[] bs = uri.getBytes();
        byte[] temp = new byte[bs.length];
        
        boolean flag = false;
        for (int i = 1; i < bs.length; i++) {
            if (bs[i] == '/') {
                flag = true;
                break;
            } else {
                temp[i-1] = bs[i];
            }
        }
        
        String prefix = "";
        if (flag) {
            prefix = new String(temp).trim();
        } else {
            return defaultPrefixTarget;
        }
        
        for (PrefixTarget prefixTarget : prefixTargetList) {
            if (prefix.equals(prefixTarget.getPrefix())) {
                return prefixTarget;
            }
        }
        
        return defaultPrefixTarget;
    }
    
    public String getTargetPath(String uri) {
        byte[] bs = uri.getBytes();
        byte[] temp1 = new byte[bs.length];
        byte[] temp2 = new byte[bs.length];
        
        boolean flag = false;
        for (int i = 1; i < bs.length; i++) {
            if (!flag && bs[i] == '/') {
                flag = true;
                temp2[i-1] = bs[i];
                continue;
            } else {
                if (!flag) {
                    temp1[i-1] = bs[i];
                } else {
                    temp2[i-1] = bs[i];
                }
            }
        }
        
        String prefix = "";
        if (flag) {
            prefix = new String(temp1).trim();
        }
        String path = new String(temp2).trim();
        
        for (PrefixTarget prefixTarget : prefixTargetList) {
            if (prefix.equals(prefixTarget.getPrefix())) {
                return prefixTarget.getTarget()+path;
            }
        }
        
        return uri;
    }
    
    public void changePrefixTarget(String uri, String target) {
        PrefixTarget prefixTarget = findPrefixTarget(uri);
        if (prefixTarget.getPrefix().isEmpty()) {
            unregistry(base, prefixTarget);
            prefixTarget.setTarget(target);
            registry(base, prefixTarget);
        } else {
            String path = new StringBuilder("/").append(prefixTarget.getPrefix()).append("/**").toString();
            unregistry(path, prefixTarget);
            prefixTarget.setTarget(target);
            registry(path, prefixTarget);
        }
    }
    
    private void unregistry(String path, PrefixTarget prefixTarget) {
        if (prefix.contains(":")) {
            registrys.unregistry(path, prefix+prefixTarget.getTarget()+"/");
        } else {
//            String resource = "classpath:/"+prefix+prefixTarget.getTarget()+"/";
//            if (applicationContext.getResource(resource).exists()) {
//                registrys.unregistry(path, resource);
//            } else {
//                registrys.unregistry(path, "file:"+prefix+prefixTarget.getTarget()+"/");
//            }
            String resource = prefix+prefixTarget.getTarget()+"/";
            registrys.unregistry(path, "file:"+resource, "classpath:/"+resource);
        }
    }
    private void registry(String path, PrefixTarget prefixTarget) {
        if (prefix.contains(":")) {
            registrys.registry(path, prefix+prefixTarget.getTarget()+"/");
        } else {
//            String resource = "classpath:/"+prefix+prefixTarget.getTarget()+"/";
//            if (applicationContext.getResource(resource).exists()) {
//                registrys.registry(path, resource);
//            } else {
//                registrys.registry(path, "file:"+prefix+prefixTarget.getTarget()+"/");
//            }
            String resource = prefix+prefixTarget.getTarget()+"/";
            registrys.registry(path, "file:"+resource, "classpath:/"+resource);
        }
    }
    
}
